<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
import { 
  Upload, 
  Button, 
  Image, 
  Card, 
  Progress, 
  message,
  Modal
} from 'ant-design-vue';
import type { UploadProps, UploadFile } from 'ant-design-vue';

// 组件属性定义
interface ImageUploadProps {
  modelValue?: string | string[]; // 支持单个和多个文件URL
  multiple?: boolean; // 是否支持多选
  maxCount?: number; // 最大文件数量
  maxSize?: number; // 最大文件大小（MB）
  accept?: string; // 接受的文件类型
  disabled?: boolean; // 是否禁用
  listType?: 'text' | 'picture' | 'picture-card'; // 列表类型
  showPreview?: boolean; // 是否显示预览
  uploadText?: string; // 上传按钮文字
  dragUpload?: boolean; // 是否支持拖拽上传
}

const props = withDefaults(defineProps<ImageUploadProps>(), {
  multiple: false,
  maxCount: 1,
  maxSize: 10, // 默认10MB
  accept: 'image/*',
  disabled: false,
  listType: 'picture-card',
  showPreview: true,
  uploadText: '点击上传',
  dragUpload: true,
});

// 事件定义
const emit = defineEmits<{
  'update:modelValue': [value: string | string[]];
  'change': [fileList: UploadFile[]];
  'preview': [file: UploadFile];
  'remove': [file: UploadFile];
}>();

// 响应式数据
const fileList = ref<UploadFile[]>([]);
const previewVisible = ref(false);
const previewImage = ref('');
const previewTitle = ref('');
const uploading = ref(false);

// 计算属性
const isMultiple = computed(() => props.multiple);
const canUpload = computed(() => {
  if (!isMultiple.value) return fileList.value.length === 0;
  return fileList.value.length < props.maxCount;
});

// 监听modelValue变化，同步到fileList
watch(() => props.modelValue, (newValue) => {
  if (!newValue) {
    fileList.value = [];
    return;
  }
  
  const urls = Array.isArray(newValue) ? newValue : [newValue];
  fileList.value = urls.map((url, index) => ({
    uid: `${index}`,
    name: `image-${index + 1}`,
    status: 'done',
    url,
  }));
}, { immediate: true });

// 文件上传前的验证
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
  // 文件类型验证
  const isImage = file.type?.startsWith('image/');
  if (!isImage) {
    message.error('只能上传图片文件！');
    return false;
  }

  // 文件大小验证
  const isLimitSize = file.size / 1024 / 1024 < props.maxSize;
  if (!isLimitSize) {
    message.error(`图片大小不能超过 ${props.maxSize}MB！`);
    return false;
  }

  // 数量限制验证
  if (!canUpload.value) {
    message.error(`最多只能上传 ${props.maxCount} 张图片！`);
    return false;
  }

  return true;
};

// 自定义上传处理
const customRequest: UploadProps['customRequest'] = (options) => {
  const { file, onSuccess, onError, onProgress } = options;
  
  // 模拟上传过程
  uploading.value = true;
  
  // 创建 FileReader 读取文件
  const reader = new FileReader();
  reader.onload = (e) => {
    const result = e.target?.result as string;
    
    // 模拟上传进度
    let progress = 0;
    const timer = setInterval(() => {
      progress += 10;
      onProgress?.({ percent: progress });
      
      if (progress >= 100) {
        clearInterval(timer);
        uploading.value = false;
        
        // 模拟上传成功，返回文件URL
        onSuccess?.(result, file);
        
        // 触发change事件
        handleChange();
      }
    }, 100);
  };
  
  reader.onerror = () => {
    uploading.value = false;
    onError?.(new Error('文件读取失败'));
  };
  
  reader.readAsDataURL(file as File);
};

// 处理文件列表变化
const handleChange = () => {
  // 更新modelValue
  const urls = fileList.value
    .filter(file => file.status === 'done')
    .map(file => file.url || file.response)
    .filter(Boolean);
  
  if (props.multiple) {
    emit('update:modelValue', urls);
  } else {
    emit('update:modelValue', urls[0] || '');
  }
  
  emit('change', [...fileList.value]);
};

// 预览图片
const handlePreview = (file: UploadFile) => {
  if (!props.showPreview) return;
  
  previewImage.value = file.url || file.response || '';
  previewVisible.value = true;
  previewTitle.value = file.name || '';
  
  emit('preview', file);
};

// 移除文件
const handleRemove = (file: UploadFile) => {
  emit('remove', file);
  handleChange();
};

// 关闭预览
const handleCancelPreview = () => {
  previewVisible.value = false;
};
</script>

<template>
  <div class="image-upload-wrapper">
    <Upload
      v-model:file-list="fileList"
      :list-type="listType"
      :multiple="multiple"
      :max-count="maxCount"
      :accept="accept"
      :disabled="disabled"
      :before-upload="beforeUpload"
      :custom-request="customRequest"
      :show-upload-list="{
        showPreviewIcon: showPreview,
        showRemoveIcon: !disabled,
        showDownloadIcon: false,
      }"
      @preview="handlePreview"
      @remove="handleRemove"
      class="image-upload"
    >
      <!-- 拖拽上传区域 -->
      <template v-if="dragUpload && listType === 'picture-card'">
        <div v-if="canUpload" class="upload-area">
          <div class="upload-icon">
            <div class="upload-icon-plus">+</div>
          </div>
          <div class="upload-text">{{ uploadText }}</div>
        </div>
      </template>
      
      <!-- 按钮上传 -->
      <template v-else-if="listType !== 'picture-card'">
        <Button 
          :disabled="disabled || !canUpload"
          :loading="uploading"
        >
          {{ uploadText }}
        </Button>
      </template>
      
      <!-- 卡片式上传按钮 -->
      <template v-else>
        <div v-if="canUpload" class="upload-button">
          <div class="upload-icon-plus">+</div>
          <div class="upload-text">{{ uploadText }}</div>
        </div>
      </template>
    </Upload>

    <!-- 图片预览Modal -->
    <Modal
      v-model:open="previewVisible"
      :title="previewTitle"
      :footer="null"
      centered
      width="80%"
      @cancel="handleCancelPreview"
    >
      <Image
        :src="previewImage"
        style="width: 100%"
        :preview="false"
      />
    </Modal>
  </div>
</template>

<style scoped>
.image-upload-wrapper {
  width: 100%;
}

.image-upload :deep(.ant-upload-select-picture-card) {
  width: 120px;
  height: 120px;
  margin-right: 8px;
  margin-bottom: 8px;
  border: 1px dashed #d9d9d9;
  border-radius: 8px;
  background-color: #fafafa;
  transition: all 0.3s ease;
}

.image-upload :deep(.ant-upload-select-picture-card:hover) {
  border-color: #1890ff;
  background-color: #f0f9ff;
}

.upload-area,
.upload-button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 16px;
  text-align: center;
  cursor: pointer;
}

.upload-icon {
  margin-bottom: 8px;
}

.upload-icon-plus {
  font-size: 24px;
  font-weight: bold;
  color: #999;
  line-height: 1;
}

.upload-text {
  font-size: 14px;
  color: #666;
  margin-top: 8px;
}

.image-upload :deep(.ant-upload-list-picture-card .ant-upload-list-item) {
  width: 120px;
  height: 120px;
  margin-right: 8px;
  margin-bottom: 8px;
  border-radius: 8px;
  overflow: hidden;
}

.image-upload :deep(.ant-upload-list-picture-card .ant-upload-list-item-info) {
  height: 100%;
}

.image-upload :deep(.ant-upload-list-picture-card .ant-upload-list-item-image) {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 拖拽样式 */
.image-upload :deep(.ant-upload-drag) {
  border: 2px dashed #d9d9d9;
  border-radius: 8px;
  background-color: #fafafa;
  padding: 24px;
  text-align: center;
  transition: all 0.3s ease;
}

.image-upload :deep(.ant-upload-drag:hover) {
  border-color: #1890ff;
  background-color: #f0f9ff;
}

.image-upload :deep(.ant-upload-drag.ant-upload-drag-hover) {
  border-color: #1890ff;
  background-color: #f0f9ff;
}

/* 上传进度样式 */
.image-upload :deep(.ant-upload-list-picture-card .ant-upload-list-item-uploading) {
  border: 1px solid #1890ff;
}

.image-upload :deep(.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-image) {
  filter: blur(1px);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .image-upload :deep(.ant-upload-select-picture-card) {
    width: 100px;
    height: 100px;
  }
  
  .image-upload :deep(.ant-upload-list-picture-card .ant-upload-list-item) {
    width: 100px;
    height: 100px;
  }
  
  .upload-icon-plus {
    font-size: 20px;
  }
  
  .upload-text {
    font-size: 12px;
  }
}
</style> 